package pt.elvis.revanweb.client.uiBinders;

import pt.elvis.revanweb.client.RevanWeb;
import pt.elvis.revanweb.client.DatabaseObjects.DatabaseHelper;
import pt.elvis.revanweb.client.DatabaseObjects.MyRequestCallback;

import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.json.client.JSONObject;
import com.google.gwt.json.client.JSONParser;
import com.google.gwt.json.client.JSONValue;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.FileUpload;
import com.google.gwt.user.client.ui.FlexTable;
import com.google.gwt.user.client.ui.FormPanel;
import com.google.gwt.user.client.ui.FormPanel.SubmitCompleteEvent;
import com.google.gwt.user.client.ui.FormPanel.SubmitCompleteHandler;
import com.google.gwt.user.client.ui.Hidden;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.Image;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.PopupPanel;
import com.google.gwt.user.client.ui.PopupPanel.PositionCallback;
import com.google.gwt.user.client.ui.SimplePanel;
import com.google.gwt.user.client.ui.SubmitButton;
import com.google.gwt.user.client.ui.TextBox;
import com.google.gwt.user.client.ui.VerticalPanel;


/**
 * @author <b>Elvis Pestana</b>
 * @author It's my implementation of a editable table, using FlexTable.
 *         It's possible to edit data on the table dynamically and change
 *         the image associated with a bookmark without having to reload the table.
 *         It also includes buttons.
 **/

public class EditableFlexTable extends VerticalPanel { // The Vertical Panel holds everything together
	private final String SESSION_ID;
	//private int currentPage = 1;
	private int currentRow = 0;
	private final int rowsPerPage; //How many rows will the table show per page?
	private FlexTable flexTable = new FlexTable(); //The main table
	private final String[] headers = {"ID", "Bookmark", "URL", "Description", "Image", "Active" }; //The headers
	private HorizontalPanel hpButtonWrapper = new HorizontalPanel(); //Wraps the buttons horizontally
	private SimplePanel simple = new SimplePanel(hpButtonWrapper); //Wraps the hpButtonWrapper
	private Button btnBack = new Button("&larr;");
	private Button btnNext = new Button("&rarr;");
	private Button btnSave = new Button("Save");
	
	private PopupPanel ppNewImage = new PopupPanel(); //where the Bookmark Image can be changed
	
	private Boolean isEditing = false;
	private int currentEditingRow = -1;
	private TextBox tbName = new TextBox();
	private String nameTemp;
	private TextBox tbURL = new TextBox();
	private String urlTemp;
	private TextBox tbDescription = new TextBox();
	private String descriptionTemp;
	private final String activeImgURL = "assets/active.png";
	private final String InactiveImgURL = "assets/not_active.png";
	
	
	public EditableFlexTable(int rowsPerPage, String SESSION_ID) {
		super();
		this.rowsPerPage = rowsPerPage + 1; // +1 because of headers.
		this.SESSION_ID = SESSION_ID;		
		setWidth("100%");
		setStylePrimaryName("editTab");
		tableStyles();
		add(flexTable);
		add(simple);
		buildButtons();
		buildEditEvents();
		addInputStyles();
	}	
	

	public void buildEditableFlexTable() {
		flexTable.removeAllRows();		
		buildTable();
	}

	private void buildTable() {
		builTableHeaders();
		int lastIndex = 0;
		int row;
		for (int i = currentRow; i < RevanWeb.bookmarksList.size(); i++) {
			lastIndex = i;			
			row = flexTable.getRowCount();
			if (row < rowsPerPage) {
				String[] values = {""+RevanWeb.bookmarksList.get(i).getIdBookmark(), RevanWeb.bookmarksList.get(i).getBookmarkName(), RevanWeb.bookmarksList.get(i).getBookmarkURL(), RevanWeb.bookmarksList.get(i).getBookmarkDescription()};
								
				for (int column = 0; column < values.length; column++) {
					flexTable.setText(row, column, values[column]);
					//flexTable.setWidget(row, column, new Label(values[column]));
				}
				
				/*
				 * Image view/editing section
				 */
				
				final String bookmarkName = RevanWeb.bookmarksList.get(i).getBookmarkName();
				final String imgURL = RevanWeb.bookmarksList.get(i).getBookmarkImagePath();
				final int idBookmark = RevanWeb.bookmarksList.get(i).getIdBookmark();
				Label lblChooseImage = new Label("Change Image...");
				lblChooseImage.setTitle(imgURL);
				flexTable.setWidget(row, 4, lblChooseImage);
				lblChooseImage.setStyleName("editTable-linkImg");
				lblChooseImage.addClickHandler(getLabelChooseImageHandler(idBookmark, bookmarkName, imgURL, i));
				
				
				//Active/Inactive section
				final Image imgActive = new Image();
				imgActive.setStyleName("editTable-imgActive");
				if (RevanWeb.bookmarksList.get(i).getActive()) {
					imgActive.setUrl(activeImgURL);
					flexTable.setWidget(row, 5, imgActive);
				} else {
					imgActive.setUrl(InactiveImgURL);
					flexTable.setWidget(row, 5, imgActive);
				}
				final int pos = i;
				imgActive.addClickHandler(new ClickHandler() {
					
					@Override
					public void onClick(ClickEvent event) {
						String phpFileName = "activate_deactive.php";
						String variavel = "sessionid=" + SESSION_ID + "&idBookmark=" + idBookmark;
						DatabaseHelper.getData_POST(phpFileName, variavel, new MyRequestCallback() {
							
							@Override
							protected void onText(String text) {								
								JSONValue value = JSONParser.parseStrict(text);
								JSONObject obj = value.isObject();
								if (obj.get("Success").isString().stringValue().equals("true")) {
									RevanWeb.reloadBookmarks = true;
									RevanWeb.bookmarksList.get(pos).swapActive();
									if (RevanWeb.bookmarksList.get(pos).getActive())
										imgActive.setUrl(activeImgURL);
									else
										imgActive.setUrl(InactiveImgURL);
								} else if (obj.get("Success").isString().stringValue().equals("false")) {
									Window.alert("Query failed - Check Firebug");
								} else {
									Window.alert("something is wrong in imgActive.addClickHandler(new ClickHandler() {");
								}
							}
						});
					}
				});
			} else {
				lastIndex--;
				currentRow = i;
				break;
			}
		}
		if (lastIndex + 1 == RevanWeb.bookmarksList.size()) {
			setEnabledButtonNext(false);
			int aux = (RevanWeb.bookmarksList.size() - 1) % (rowsPerPage - 1);
			aux = (rowsPerPage - 1) - aux;
			if (!(aux == (rowsPerPage - 1)))
				currentRow = lastIndex + aux;
		}
		if (currentRow <= rowsPerPage) {
			setEnabledButtonBack(false);
		}
	}
	
	
	private ClickHandler getLabelChooseImageHandler(final int idBookmark, final String bookmarkName, final String imgURL, final int index) {
		return new ClickHandler() {
			
			@Override
			public void onClick(ClickEvent event) {
				ppNewImage.clear();
				ppNewImage.setAnimationEnabled(true);
				ppNewImage.setGlassEnabled(true);
				VerticalPanel vpNewImage = new VerticalPanel();
				Image imgBtnClose = new Image("assets/close.svg");
				imgBtnClose.setTitle("Close without saving");
				imgBtnClose.setStyleName("editTable-closeImgButton");
				imgBtnClose.addClickHandler(new ClickHandler() {
					
					@Override
					public void onClick(ClickEvent event) {
						ppNewImage.hide();
						ppNewImage.clear();
					}
				});
				vpNewImage.add(imgBtnClose);
				final Image imgOld = new Image(imgURL);
				vpNewImage.add(imgOld);
				vpNewImage.add(new Label("Image path: " + imgURL));
				final FormPanel form = new FormPanel();
				form.setAction("phpFiles/updateBookmarkImage.php");
				form.setEncoding(FormPanel.ENCODING_MULTIPART);
				form.setMethod(FormPanel.METHOD_POST);
				VerticalPanel vpForm = new VerticalPanel();
				vpForm.add(new Hidden("idBookmark", idBookmark+""));
				vpForm.add(new Hidden("sessionid", SESSION_ID));
				vpForm.add(new Hidden("oldImgPath", imgURL));
				final FileUpload uploadNewImage = new FileUpload();
				uploadNewImage.setName("newImage");
				vpForm.add(uploadNewImage);
				SubmitButton submit = new SubmitButton("Save Modifications");
				vpForm.add(submit);
				form.add(vpForm);
				
				form.addSubmitCompleteHandler(new SubmitCompleteHandler() {
					
					@Override
					public void onSubmitComplete(SubmitCompleteEvent event) {
						//Parse returned String and check for results
						String[] result = parse(event.getResults());
						if (result[0].equals("true")) {
							// Everything works fine
							imgOld.setUrl(result[1]);
							ppNewImage.center();
							for (int i = 0; i < RevanWeb.bookmarksList.size(); i++) {
								if (RevanWeb.bookmarksList.get(i).getIdBookmark() == idBookmark)
									RevanWeb.bookmarksList.get(i).setBookmarkImagePath(result[1]);
							}
							for (int j = 0; j < RevanWeb.imageAnchorList.size(); j++) {
								if (RevanWeb.imageAnchorList.get(j).getIdBookmark() == idBookmark)
									RevanWeb.imageAnchorList.get(j).resetImage(result[1]);
							}
						} else {
							Window.alert("WHOOOssss");
						}
					}

					private String[] parse(String results) {
						String[] val = {"", ""};
						JSONValue value = JSONParser.parseStrict(results);
						JSONObject obj = value.isObject();
						
						if (obj.get("Success").isString().stringValue().equals("true")) {
							val[0] = "true";
							val[1] = obj.get("imgPath").isString().stringValue();
						} else {
							val[0] = "false";
							val[1] = obj.get("Cause").isString().stringValue();
						}
						return val;
					}
				});
				vpNewImage.add(form);
				ppNewImage.add(vpNewImage);
				ppNewImage.setPopupPositionAndShow(new PositionCallback() {
					
					@Override
					public void setPosition(int offsetWidth, int offsetHeight) {
						int left = ((Window.getClientWidth() - offsetWidth) / 2 );
                        int top = ((Window.getClientHeight() - offsetHeight) / 4);
                        ppNewImage.setPopupPosition(left, top);
					}
				});
			}
		};
		
	}
	
	private void buildEditEvents() {
		flexTable.addClickHandler(new ClickHandler() {
			
			@Override
			public void onClick(ClickEvent event) {
				if (!isEditing) {
					final int row = flexTable.getCellForEvent(event).getRowIndex();
					final int column = flexTable.getCellForEvent(event).getCellIndex();
					if ((row != 0) && (column != 5) && (column != 4)) {
						for (int i = 0; i <= 5; i++)							
							flexTable.getCellFormatter().setStyleName(row, i, "editTable-editRow-selected");
						currentEditingRow = row;
						nameTemp = flexTable.getText(row, 1);
						tbName.setText(nameTemp);
						urlTemp = flexTable.getText(row, 2);
						tbURL.setText(urlTemp);
						descriptionTemp = flexTable.getText(row, 3);
						tbDescription.setText(descriptionTemp);
						
						flexTable.setWidget(row, 1, tbName);
						flexTable.setWidget(row, 2, tbURL);
						flexTable.setWidget(row, 3, tbDescription);
						
						tbName.setWidth("95%");
						tbURL.setWidth("95%");
						tbDescription.setWidth("95%");
						tbName.setFocus(true);
						isEditing = true;
						setEnabledButtonSave(true);
					}
				}
			}
		});
	}
	
	private void buildButtons() {
		setEnabledButtonBack(false);
		btnBack.addClickHandler(new ClickHandler() {
			
			@Override
			public void onClick(ClickEvent event) {
				if (isEditing)
					isEditing = false;
				flexTable.clear(true);
				flexTable.removeAllRows();
				currentRow = currentRow - ((rowsPerPage - 1) * 2);
				buildTable();
				setEnabledButtonNext(true);
			}
		});
		
		setEnabledButtonNext(true);
		btnNext.addClickHandler(new ClickHandler() {
			
			@Override
			public void onClick(ClickEvent event) {
				if (isEditing)
					isEditing = false;
				flexTable.clear(true);
				flexTable.removeAllRows();
				buildTable();
				setEnabledButtonBack(true);
				
			}
		});
		
		setEnabledButtonSave(false);
		btnSave.addClickHandler(new ClickHandler() {
			
			@Override
			public void onClick(ClickEvent event) {
				//Update bookmark fields here.
				saveChanges(tbName.getText(), tbURL.getText(), tbDescription.getText());
				updateRow();
			}
		});
		hpButtonWrapper.add(btnBack);
		hpButtonWrapper.add(btnNext);
		hpButtonWrapper.add(btnSave);
	}
	
	private void saveChanges(String newName, String newURL, String newDescription) {
		if (checkIfValueChanged(newName, newURL, newDescription)) {
			final String idBookmark = flexTable.getText(currentEditingRow, 0);
			String phpFileName = "updateBookmark.php";
			String variavel = "idBookmark=" + idBookmark + "&bookmarkName=" + tbName.getText() + "&bookmarkURL=" + tbURL.getText() + "&bookmarkDescription=" + tbDescription.getText() + "&sessionid=" + SESSION_ID; 
			DatabaseHelper.getData_POST(phpFileName, variavel, new MyRequestCallback() {
				
				@Override
				protected void onText(String text) {
					JSONValue value = JSONParser.parseStrict(text);
					JSONObject obj = value.isObject();
					if (obj.get("Success").isString().stringValue().equals("true")) {
						for (int i = 0; i < RevanWeb.bookmarksList.size(); i++) {
							if (RevanWeb.bookmarksList.get(i).getIdBookmark() == Integer.parseInt(idBookmark)) {
								RevanWeb.bookmarksList.get(i).setBookmarkName(tbName.getText());
								RevanWeb.bookmarksList.get(i).setBookmarkURL(tbURL.getText());
								RevanWeb.bookmarksList.get(i).setBookmarkDescription(tbDescription.getText());
							}
						}						
					} else if (obj.get("Success").isString().stringValue().equals("false"))
						Window.alert("Something is wrong: private void buildButtons()\n" + text);
					else
						Window.alert("Something is wrong: private void buildButtons()\n" + text);
				}
			});
		}
	}
	
	private boolean checkIfValueChanged(String newName, String newURL, String newDescription) {
		if (newName.equals(nameTemp) && (newURL.equals(urlTemp)) && (newDescription.equals(descriptionTemp)))
			return false;
		else
			return true;
	}
	
	private void updateRow() {
		flexTable.setText(currentEditingRow, 1, tbName.getText());
		flexTable.setText(currentEditingRow, 2, tbURL.getText());
		flexTable.setText(currentEditingRow, 3, tbDescription.getText());
		for (int i = 0; i <= 5; i++)
			flexTable.getCellFormatter().removeStyleName(currentEditingRow, i, "editTable-editRow-selected");
		isEditing = false;
		setEnabledButtonSave(false);
	}
	

	private void builTableHeaders() {
		int row = flexTable.getRowCount();
		for (int column = 0; column < 6; column++) {
			//flexTable.setWidget(row, column, new Label(headers[column]));
			flexTable.setText(row, column, headers[column]);
			flexTable.getRowFormatter().addStyleName(row, "editTable-headers");
		}
	}
	
	private void setEnabledButtonNext(boolean enabled) {		
		btnNext.setEnabled(enabled);
		if (enabled) {
			btnNext.removeStyleName("disabled");
			btnNext.addStyleName("button");
		} else {
			btnNext.removeStyleName("button");
			btnNext.addStyleName("disabled");
		}
	}
	private void setEnabledButtonBack(boolean enabled) {		
		btnBack.setEnabled(enabled);
		if (enabled) {
			btnBack.addStyleName("button");
			btnBack.removeStyleName("disabled");
		} else {
			btnBack.removeStyleName("button");
			btnBack.addStyleName("disabled");
		}
	}
	private void setEnabledButtonSave(boolean enabled) {		
		btnSave.setEnabled(enabled);
		if (enabled) {
			btnSave.addStyleName("button");
			btnSave.removeStyleName("disabled");
		} else {
			btnSave.removeStyleName("button");
			btnSave.addStyleName("disabled");
		}
	}
	
	private void addInputStyles() {
		tbName.setStyleName("editTable-editRow");
		tbURL.setStyleName("editTable-editRow");
		tbDescription.setStyleName("editTable-editRow");
	}
	
	private void tableStyles() {
		flexTable.setWidth("100%");
		flexTable.setStylePrimaryName("editTable");
		for (int i = 0; i <= 5; i++)
			flexTable.getColumnFormatter().setStyleName(i, "editTable-" + i);
	}

	public int getCurrentRow() {
		return currentRow;
	}

	public void setCurrentRow(int currentRow) {
		this.currentRow = currentRow;
	}
}